package com.dingreading.cloud.common.util;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class DoubleUtil {

    /**
     * （Double强转Int）精度丢失问题
     */
    public static int formatDoubleTOInt(double dou1, double dou2) {
        BigDecimal big1 = new BigDecimal(Double.toString(dou1)).setScale(2, RoundingMode.HALF_UP);
        BigDecimal big2 = new BigDecimal(Double.toString(dou2));
        return big1.multiply(big2).intValue();
    }

    /**
     * double 相加
     */
    public static double sum(double d1, double d2) {
        BigDecimal bd1 = new BigDecimal(Double.toString(d1));
        BigDecimal bd2 = new BigDecimal(Double.toString(d2));
        return bd1.add(bd2).doubleValue();
    }


    /**
     * double 相减
     */
    public static double sub(double d1, double d2) {
        BigDecimal bd1 = new BigDecimal(Double.toString(d1));
        BigDecimal bd2 = new BigDecimal(Double.toString(d2));
        return bd1.subtract(bd2).doubleValue();
    }

    /**
     * double 乘法
     */
    public static double mul(double d1, double d2) {
        BigDecimal bd1 = new BigDecimal(Double.toString(d1));
        BigDecimal bd2 = new BigDecimal(Double.toString(d2));
        return bd1.multiply(bd2).doubleValue();
    }

    /**
     * double 乘法
     */
    public static double mul(double d1, double d2, int scale) {
        BigDecimal bd1 = new BigDecimal(Double.toString(d1));
        BigDecimal bd2 = new BigDecimal(Double.toString(d2));
        BigDecimal multiply = bd1.multiply(bd2);
        // 设置四舍五入模式，保留2位小数
        multiply = multiply.setScale(2, RoundingMode.HALF_UP);
        return multiply.doubleValue();
    }

    /**
     * double 除法
     *
     * @param scale 四舍五入 小数点位数
     */
    public static double div(double d1, double d2, int scale) {
        //  当然在此之前，你要判断分母是否为0，
        //  为0你可以根据实际需求做相应的处理
        BigDecimal bd1 = new BigDecimal(Double.toString(d1));
        BigDecimal bd2 = new BigDecimal(Double.toString(d2));
        return bd1.divide(bd2, scale, RoundingMode.HALF_UP).doubleValue();
    }


    /**
     * double 除法,当分母为0 返回0
     *
     * @param scale 四舍五入 小数点位数
     */
    public static double divZero(double d1, double d2, int scale) {
        if (d2 == 0) {
            if (scale == 2) {
                d2 = 0.00d;
            }
            return d2;
        }
        return div(d1, d2, scale);
    }

    /**
     * double 除法，向下取整
     *
     * @param scale 四舍五入 小数点位数
     */
    public static double divFloor(double d1, double d2, int scale) {
        //  当然在此之前，你要判断分母是否为0，
        //  为0你可以根据实际需求做相应的处理
        BigDecimal bd1 = new BigDecimal(Double.toString(d1));
        BigDecimal bd2 = new BigDecimal(Double.toString(d2));
        return bd1.divide(bd2, scale, RoundingMode.FLOOR).doubleValue();
    }

    /**
     * double 除法，向上取整
     *
     * @param scale 四舍五入 小数点位数
     */
    public static double divCeil(double d1, double d2, int scale) {
        //  当然在此之前，你要判断分母是否为0，
        //  为0你可以根据实际需求做相应的处理
        BigDecimal bd1 = new BigDecimal(Double.toString(d1));
        BigDecimal bd2 = new BigDecimal(Double.toString(d2));
        return bd1.divide(bd2, scale, RoundingMode.CEILING).doubleValue();
    }

    /**
     * 提供（相对）精确的除法运算。 当发生除不尽的情况时，由scale参数指定精度，以后的数字四舍五入。
     *
     * @param d1    被除数
     * @param d2    除数
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static Double divide(double d1, double d2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(d1));
        BigDecimal b2 = new BigDecimal(Double.toString(d2));
        return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 提供指定数值的（精确）小数位四舍五入处理。
     *
     * @param value 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double value, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(value));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * double 转 string 去掉后面锝0
     */
    public static String getString(double i) {
        String s = Double.toString(i);
        if (s.indexOf(".") > 0) {
            //正则表达
            //去掉后面无用的零
            s = s.replaceAll("0+?$", "");
            //如小数点后面全是零则去掉小数点
            s = s.replaceAll("[.]$", "");
        }
        return s;
    }

    /**
     * 数字转换为千位符
     */
    public static String numberToBits(String number) {
        String begin = "";
        String end = "";
        String[] num = number.split("\\.");
        if (num.length > 1) {
            begin = num[0];
            end = num[1];
        } else {
            begin = number;
        }
        return begin.replaceAll("(?<=\\d)(?=(?:\\d{3})+$)", ",") + "." + end;
    }


    /**
     * 转换为中国人民币大写字符串,精确到分
     *
     * @param money 传入小写数字字符串
     * @return String
     */
    public static String toRMBUpper(String money) throws Exception {
        boolean lessZero = false;
        //When money is scientific notation
        if (money.contains("E")) {
            BigDecimal bg = new BigDecimal(money);
            money = bg.toPlainString();
        }
        if (money.startsWith("-")) {
            money = money.substring(1);
            lessZero = true;
        }

        if (!money.matches("^[0-9]*$|^0+\\.[0-9]+$|^[1-9]+[0-9]*$|^[1-9]+[0-9]*.[0-9]+$")) {
            throw new Exception("钱数格式错误");
        }
        String[] parts = money.split("\\.");
        String integerData = parts[0];
        String decimalData = parts.length > 1 ? parts[1] : "";
        //Replace front 0
        if (integerData.matches("^0+$")) {
            integerData = "0";
        } else if (integerData.matches("^0+(\\d+)$")) {
            integerData = integerData.replaceAll("^0+(\\d+)$", "$1");
        }

        StringBuilder integer = new StringBuilder();
        for (int i = 0; i < integerData.length(); i++) {
            char perChar = integerData.charAt(i);
            integer.append(upperNumber(perChar));
            integer.append(upperNumber(integerData.length() - i - 1));
        }
        StringBuilder decimal = new StringBuilder();
        if (parts.length > 1 && !"00".equals(decimalData)) {
            int length = Math.min(decimalData.length(), 2);
            for (int i = 0; i < length; i++) {
                char perChar = decimalData.charAt(i);
                decimal.append(upperNumber(perChar));
                if (i == 0)
                    decimal.append('角');
                if (i == 1)
                    decimal.append('分');
            }
        }
        String result = integer.append(decimal).toString();
        result = dispose(result);
        if (lessZero && !"零元整".equals(result)) {
            result = "负" + result;
        }
        return result;
    }

    private static char upperNumber(char number) {
        switch (number) {
            case '0':
                return '零';
            case '1':
                return '壹';
            case '2':
                return '贰';
            case '3':
                return '叁';
            case '4':
                return '肆';
            case '5':
                return '伍';
            case '6':
                return '陆';
            case '7':
                return '柒';
            case '8':
                return '捌';
            case '9':
                return '玖';
        }
        return '0';
    }

    private static char upperNumber(int index) {
        int realIndex = index % 9;
        if (index > 8) {
            realIndex = (index - 9) % 8;
            realIndex = realIndex + 1;
        }
        switch (realIndex) {
            case 0:
                return '元';
            case 1:
            case 5:
                return '拾';
            case 2:
            case 6:
                return '佰';
            case 3:
            case 7:
                return '仟';
            case 4:
                return '万';
            case 8:
                return '亿';
        }
        return '0';
    }

    private static String dispose(String result) {
        result = result.replaceAll("0", "");
        result = result.replaceAll("零仟零佰零拾|零仟零佰|零佰零拾|零仟|零佰|零拾", "零");
        result = result.replaceAll("零+", "零").replace("零亿", "亿");
        result = result.matches("^.*亿零万[^零]仟.*$") ? result.replace("零万", "零") : result.replace("零万", "万");
        result = result.replace("亿万", "亿");
        //Processing decimals
        result = result.replace("零角", "零").replace("零分", "");
        result = result.replaceAll("(^[零元]*)(.+$)", "$2");
        result = result.replaceAll("(^.*)([零]+元)(.+$)", "$1元零$3");

        //Processing integer
        result = result.replaceAll("元零角零分|元零角$|元$|^零$|元零$|元零零$|零元$", "元");
        result = result.replaceAll("^元$", "零元");


        return result;
    }


    public static void main(String[] args) throws Exception {
        //Test
        System.out.println(toRMBUpper("-1110"));

        System.out.println(toRMBUpper("-1110.21"));
    }

}